#include <QSqlQuery>

#include "../global/QmlNames.h"
#include "../util/Singleton.h"
#include "../persist/DbManager.h"
#include "GroupsModel.h"

X_BEGIN_NAMESPACE

enum RoleNames{
    id,
    name,
    photo,
    photoType,
    createTime,
    mute,
    members,
    DATA_ROLE_MAX
};

const char* GroupsModel::ROLE_NAMES[] = {
    "id",
    "name",
    "photo",
    "photoType",
    "createTime",
    "mute",
    "members"
};
const char GroupsModel::READ_GROUPS[] = "select g.id, g.name, g.photo, g.photo_type, g.create_time, g.mute from groups g order by g.name";

GroupsModel::GroupsModel(QObject* parent)
    : QAbstractListModel(parent)
{
    for(int i = id; i < DATA_ROLE_MAX; ++i){
        m_roleNames.insert(i, ROLE_NAMES[i]);
    }
}

GroupsModel &GroupsModel::instance()
{
    return *Singleton<GroupsModel>::instance(GroupsModel::createInstance);
}

const char *GroupsModel::qmlName()
{
    return QmlNames::TopLevelModelSingleton::GroupsSingleton;
}

QObject *GroupsModel::qmlInstance(QQmlEngine *engine, QJSEngine *jsEngine)
{
    Q_UNUSED(engine);
    Q_UNUSED(jsEngine);

    return &instance();
}

int GroupsModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return m_groups.size();
}

QVariant GroupsModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid()) return QVariant("");

    GroupModel* group = m_groups[index.row()];
    switch(role){
        case id:
            return group->id();
        case name:
            return group->name();
        case photo:
            return group->photo();
        case photoType:
            return (int)group->photoType();
        case createTime:
            return group->createTime();
        case mute:
            return group->mute();
        case members:
            return QVariant::fromValue(group->members());
        default:
            return QVariant("Not Implemented.");
    }
}

QHash<int, QByteArray> GroupsModel::roleNames() const
{
    return m_roleNames;
}

GroupModel& GroupsModel::addGroup(const QString &id, const QString &name, const QString &photo, const QDateTime createTime)
{
    GroupModel* group = new GroupModel(id, createTime);
    group->setName(name);
    group->setPhoto(photo);

    m_groupsById[id] = group;

    bool inserted = false;
    for(int i = 0; i < m_groups.size(); ++i){
        if(groupLessThan(m_groups[i], group)) continue;

        m_groups.insert(i, group);
    }

    if(!inserted){
        m_groups.append(group);
    }

    return *group;
}

GroupModel &GroupsModel::createGroup(const QString &id, const QString &name)
{
    // 已存在直接返回
    if(m_groupsById.contains(id)){
        return *m_groupsById[id];
    }

    // 增加
    GroupModel& group = addGroup(id, name, "qrc:/images/avatar_default_groiup.png", QDateTime::currentDateTime());

    // 发送新建信号
    int index = m_groups.indexOf(&group);
    beginInsertRows(QModelIndex(), index, index);
    endInsertRows();

    return group;
}

QObject *GroupsModel::findGroup(const QString &id) const
{
    if(m_groupsById.find(id) != m_groupsById.end()) return m_groupsById[id];

    return NULL;
}

GroupsModel *GroupsModel::createInstance()
{
    GroupsModel *inst = new GroupsModel;
    return inst;
}

bool GroupsModel::groupLessThan(GroupModel* g1, GroupModel* g2)
{
    return g1->name() < g2->name();
}

void GroupsModel::houseKeep()
{
    beginRemoveRows(QModelIndex(), 0, m_groups.size() - 1);

    foreach (GroupModel* group, m_groups) {
        delete group;
    }

    m_groups.clear();
    m_groupsById.clear();

    endRemoveRows();
}

/**
 * @brief 加载群组。
 *
 * 注意：群组成员延后加载。
 */
void GroupsModel::loadDataFromDb()
{
    try{
        //
        QSqlQuery query = DbManager::instance().createQuery();
        query.exec(READ_GROUPS);

        while(query.next()){
            // id, name, photo, photo_type, create_time, mute
            QString id = query.value("id").toString();
            QString name = query.value("name").toString();
            QString photo = query.value("photo").toString();
            PhotoType photoType = PhotoType(query.value("photo_type").toInt());
            QDateTime createTime = query.value("create_time").toDateTime();
            bool mute = query.value("mute").toBool();

            addGroup(id, name, photo, createTime)
                    .setPhotoType(photoType)
                    .setMute(mute);
        }

        beginInsertRows(QModelIndex(), 0, m_groups.size() - 1);
        endInsertRows();
    } catch(...){
        qDebug() << "Load groups from database failed.";
    }
}

X_END_NAMESPACE
